// 脚本管理器
// 提供脚本导入导出功能

import { parsePlaywrightScript, generateStepDisplayInfo, getStepIcon } from '../utils/playwrightParser.js'

/**
 * 脚本管理器类
 */
export class ScriptManager {
  constructor() {
    // 当前脚本内容和相关数据
    this.currentScript = ''
    this.currentSteps = []
    this.scriptMetadata = {
      name: '',
      format: 'playwright',
      importTime: null
    }
  }

  /**
   * 初始化脚本管理器
   */
  init() {
    console.log('脚本管理器初始化完成')
  }

  /**
   * 导入脚本
   * @param {string} scriptContent - 脚本内容
   * @param {string} format - 脚本格式
   * @returns {Object} 导入结果
   */
  importScript(scriptContent, format = 'playwright') {
    try {
      if (!scriptContent?.trim()) {
        return {
          success: false,
          message: '请输入或上传脚本内容'
        }
      }
      
      // 解析Playwright脚本
      const parsedSteps = parsePlaywrightScript(scriptContent)
      
      if (parsedSteps.length === 0) {
        return {
          success: false,
          message: '无法解析脚本内容，请确保输入的是有效的Playwright脚本'
        }
      }
      
      // 保存脚本内容和解析后的步骤
      this.currentScript = scriptContent
      this.currentSteps = parsedSteps
      this.scriptMetadata.importTime = new Date()
      
      // 提取脚本名称
      const testNameMatch = scriptContent.match(/test\(['"]([^'"]+)['"],/)
      this.scriptMetadata.name = testNameMatch ? testNameMatch[1] : 'imported_script'
      
      // 生成步骤到UI
      this.generateStepsToUI(parsedSteps)
      
      // 触发步骤导入事件
      this.dispatchStepsImportedEvent(parsedSteps, scriptContent)
      
      return {
        success: true,
        steps: parsedSteps,
        metadata: this.scriptMetadata,
        message: `脚本导入成功！解析出 ${parsedSteps.length} 个步骤`
      }
      
    } catch (error) {
      console.error('导入脚本时发生错误:', error)
      return {
        success: false,
        message: '导入脚本时发生错误: ' + error.message
      }
    }
  }

  /**
   * 导出脚本
   * @param {Object} options - 导出选项
   * @returns {Object} 导出结果
   */
  exportScript(options = {}) {
    try {
      const {
        scriptName = 'login_test',
        format = 'playwright',
        isTypeScript = false,
        steps = [],
        includeComments = true,
        includeScreenshots = false,
        prettyFormat = true,
        includeMetadata = false
      } = options
      
      let exportContent = ''
      let filename = ''
      
      if (format === 'playwright') {
        // 生成Playwright脚本
        exportContent = this.generatePlaywrightScript({
          scriptName,
          isTypeScript,
          steps,
          includeComments,
          includeScreenshots,
          prettyFormat
        })
        filename = `${scriptName}${isTypeScript ? '.ts' : '.js'}`
      } else if (format === 'jsonl') {
        // 生成JSONL格式
        exportContent = this.generateJsonlScript({
          steps,
          includeMetadata,
          prettyFormat
        })
        filename = `${scriptName}.jsonl`
      } else {
        return {
          success: false,
          message: `不支持的导出格式: ${format}`
        }
      }
      
      return {
        success: true,
        content: exportContent,
        filename: filename,
        format: format,
        stepCount: steps.length
      }
      
    } catch (error) {
      console.error('导出脚本失败:', error)
      return {
        success: false,
        message: '导出脚本失败: ' + error.message
      }
    }
  }

  /**
   * 生成Playwright脚本
   * @param {Object} options - 生成选项
   * @returns {string} 生成的脚本内容
   */
  generatePlaywrightScript(options) {
    const {
      scriptName,
      isTypeScript,
      steps,
      includeComments,
      includeScreenshots,
      prettyFormat
    } = options
    
    let script = ''
    
    // 添加导入语句
    if (isTypeScript) {
      script += "import { test, expect, Page } from '@playwright/test';\n\n"
    } else {
      script += "import { test, expect } from '@playwright/test';\n\n"
    }
    
    // 添加测试函数
    if (isTypeScript) {
      script += `test('${scriptName}', async ({ page }: { page: Page }) => {\n`
    } else {
      script += `test('${scriptName}', async ({ page }) => {\n`
    }
    
    // 添加步骤
    steps.forEach((step, index) => {
      // 添加注释
      if (includeComments && step.description) {
        script += `  // ${step.description}\n`
      }
      
      // 根据步骤类型生成代码
      switch (step.type) {
        case 'navigation':
          script += `  await page.goto('${step.url || step.selector}');\n`
          break
          
        case 'input':
        case 'type':
          if (step.action === 'type') {
            script += `  await page.type('${step.selector}', '${step.value || ''}');\n`
          } else {
            script += `  await page.fill('${step.selector}', '${step.value || ''}');\n`
          }
          break
          
        case 'click':
          if (step.action === 'dblclick') {
            script += `  await page.dblclick('${step.selector}');\n`
          } else {
            script += `  await page.click('${step.selector}');\n`
          }
          break
          
        case 'wait':
          if (step.waitType === 'element' || step.selector) {
            script += `  await page.waitForSelector('${step.selector}');\n`
          } else {
            script += `  await page.waitForTimeout(${step.duration || step.timeout || 1000});\n`
          }
          break
          
        case 'assertion':
          const assertion = step.assertion || 'toBeVisible'
          if (step.expectedValue) {
            if (assertion === 'toHaveText') {
              script += `  await expect(page.locator('${step.selector}')).toHaveText('${step.expectedValue}');\n`
            } else if (assertion === 'toContainText') {
              script += `  await expect(page.locator('${step.selector}')).toContainText('${step.expectedValue}');\n`
            } else {
              script += `  await expect(page.locator('${step.selector}')).${assertion}();\n`
            }
          } else {
            script += `  await expect(page.locator('${step.selector}')).${assertion}();\n`
          }
          break
          
        case 'screenshot':
          if (includeScreenshots) {
            const filename = step.filename || `screenshot_${index + 1}.png`
            script += `  await page.screenshot({ path: '${filename}' });\n`
          }
          break
          
        default:
          if (includeComments) {
            script += `  // 未知步骤类型: ${step.type}\n`
          }
      }
      
      // 添加空行以提高可读性
      if (prettyFormat && index < steps.length - 1) {
        script += '\n'
      }
    })
    
    script += '});'
    
    // 如果不包含注释，移除注释
    if (!includeComments) {
      script = script.replace(/\/\/.*$/gm, '').replace(/\/\*[\s\S]*?\*\//g, '')
    }
    
    return script
  }

  /**
   * 生成JSONL脚本
   * @param {Object} options - 生成选项
   * @returns {string} 生成的JSONL内容
   */
  generateJsonlScript(options) {
    const { steps, includeMetadata, prettyFormat } = options
    
    let jsonlContent = ''
    
    // 如果包含元数据，添加元数据行
    if (includeMetadata) {
      const metadata = {
        type: 'metadata',
        exportTime: new Date().toISOString(),
        totalSteps: steps.length,
        format: 'jsonl',
        version: '1.0'
      }
      jsonlContent += JSON.stringify(metadata) + '\n'
    }
    
    // 添加步骤数据
    steps.forEach(step => {
      const stepData = {
        stepNumber: step.stepNumber,
        type: step.type,
        action: step.action,
        description: step.description || step.name,
        selector: step.selector,
        value: step.value,
        url: step.url,
        timeout: step.timeout,
        assertion: step.assertion,
        expectedValue: step.expectedValue,
        filename: step.filename,
        timestamp: step.timestamp || new Date().toISOString()
      }
      
      // 移除空值
      Object.keys(stepData).forEach(key => {
        if (stepData[key] === undefined || stepData[key] === null || stepData[key] === '') {
          delete stepData[key]
        }
      })
      
      if (prettyFormat) {
        jsonlContent += JSON.stringify(stepData, null, 0) + '\n'
      } else {
        jsonlContent += JSON.stringify(stepData) + '\n'
      }
    })
    
    return jsonlContent.trim()
  }

  /**
   * 获取当前脚本内容
   * @returns {string} 当前脚本内容
   */
  getCurrentScript() {
    return this.currentScript
  }

  /**
   * 设置当前脚本内容
   * @param {string} script - 要设置的脚本内容
   */
  setCurrentScript(script) {
    this.currentScript = script
  }

  /**
   * 获取当前步骤数据
   * @returns {Array} 当前步骤数组
   */
  getCurrentSteps() {
    return this.currentSteps
  }

  /**
   * 获取脚本元数据
   * @returns {Object} 脚本元数据
   */
  getScriptMetadata() {
    return this.scriptMetadata
  }

  /**
   * 设置步骤并更新UI
   * @param {Array} steps - 步骤数组
   */
  setStepsAndUpdateUI(steps) {
    console.log('设置步骤并更新UI:', steps)
    
    // 更新当前步骤数据
    this.currentSteps = steps
    
    // 触发步骤更新事件
    this.dispatchStepsUpdatedEvent(steps)
    
    console.log('步骤设置和UI更新完成')
  }

  /**
   * 自动导入生成的脚本
   * @param {string} scriptContent - 脚本内容
   * @returns {Object} 导入结果
   */
  async autoImportGeneratedScript(scriptContent) {
    try {
      console.log('自动导入生成的脚本...')
      
      if (!scriptContent?.trim()) {
        throw new Error('脚本内容为空')
      }
      
      // 解析脚本内容
      const parsedSteps = parsePlaywrightScript(scriptContent)
      console.log(`解析结果: ${parsedSteps.length} 个步骤`)
      
      if (!Array.isArray(parsedSteps) || parsedSteps.length === 0) {
        throw new Error('无法解析脚本内容为有效步骤')
      }
      
      // 更新当前数据
      this.currentScript = scriptContent
      this.currentSteps = parsedSteps
      this.scriptMetadata = {
        name: `录制脚本_${new Date().toLocaleString()}`,
        format: 'playwright',
        importTime: new Date(),
        source: 'recording'
      }
      
      // 触发步骤导入事件
      this.dispatchStepsImportedEvent(parsedSteps, scriptContent)
      
      return {
        success: true,
        steps: parsedSteps,
        metadata: this.scriptMetadata
      }
      
    } catch (error) {
      console.error('自动导入脚本失败:', error)
      throw error
    }
  }

  /**
   * 生成步骤到UI
   * @param {Array} steps - 步骤数组
   */
  generateStepsToUI(steps) {
    console.log('生成步骤到UI:', steps)
    
    // 触发步骤生成事件，让Vue组件监听并更新UI
    this.dispatchStepsGeneratedEvent(steps)
    
    console.log('步骤UI生成完成')
  }

  /**
   * 触发步骤生成事件
   * @param {Array} steps - 步骤数组
   */
  dispatchStepsGeneratedEvent(steps) {
    if (typeof window !== 'undefined') {
      const generateEvent = new CustomEvent('stepsGenerated', {
        detail: {
          steps: steps,
          totalSteps: steps.length
        }
      })
      window.dispatchEvent(generateEvent)
    }
  }

  /**
   * 触发步骤导入事件
   * @param {Array} steps - 步骤数组
   * @param {string} scriptContent - 脚本内容
   */
  dispatchStepsImportedEvent(steps, scriptContent) {
    if (typeof window !== 'undefined') {
      const importEvent = new CustomEvent('stepsImported', {
        detail: {
          scriptContent: scriptContent,
          steps: steps,
          metadata: this.scriptMetadata
        }
      })
      window.dispatchEvent(importEvent)
    }
  }

  /**
   * 触发步骤更新事件
   * @param {Array} steps - 步骤数组
   */
  dispatchStepsUpdatedEvent(steps) {
    if (typeof window !== 'undefined') {
      const updateEvent = new CustomEvent('stepsUpdated', {
        detail: {
          steps: steps,
          totalSteps: steps.length
        }
      })
      window.dispatchEvent(updateEvent)
    }
  }

  /**
   * HTML转义函数
   * @param {string} text - 需要转义的文本
   * @returns {string} 转义后的文本
   */
  escapeHtml(text) {
    const map = {
      '&': '&amp;',
      '<': '&lt;',
      '>': '&gt;',
      '"': '&quot;',
      "'": '&#039;'
    }
    return text.replace(/[&<>"']/g, m => map[m])
  }

  /**
   * 生成控制台内容
   * @param {string} scriptContent - 脚本内容
   * @returns {string} 格式化后的HTML内容
   */
  generateConsoleContent(scriptContent) {
    // 提取脚本内容，格式化为HTML
    const formattedScript = this.formatPlaywrightScript(scriptContent)
    
    return `
    <div class="p-4 h-full">
      <div class="border border-gray-200 rounded bg-gray-900 text-white p-3 h-full overflow-auto font-mono">
        <div class="flex justify-between items-center mb-3">
          <div class="flex items-center">
            <h3 class="text-sm font-medium text-gray-300 mr-3">JavaScript 控制台</h3>
            <div class="flex border border-gray-700 rounded overflow-hidden">
              <button class="px-2 py-1 text-xs bg-gray-800 text-gray-300 border-r border-gray-700">常规</button>
              <button class="px-2 py-1 text-xs bg-indigo-700 text-white">Playwright</button>
            </div>
          </div>
          <div class="flex gap-2">
            <button class="p-1 text-gray-400 hover:text-gray-200" title="清除控制台">
              <i class="fas fa-trash-alt"></i>
            </button>
            <button class="p-1 text-gray-400 hover:text-gray-200" title="运行脚本">
              <i class="fas fa-play"></i>
            </button>
          </div>
        </div>
        
        <div class="text-sm space-y-1 mb-4">
          <div class="flex items-center mb-2">
            <span class="text-xs text-gray-500 mr-2">// 已导入的 Playwright 测试脚本</span>
            <button class="text-xs text-gray-400 hover:text-gray-200 ml-auto">复制</button>
          </div>
          <div class="bg-gray-800 p-3 rounded overflow-auto max-h-[300px]">
            ${formattedScript}
          </div>
        </div>
        
        <div class="flex items-center mt-3 border-t border-gray-700 pt-3">
          <span class="text-gray-400 mr-2">&gt;</span>
          <textarea class="flex-1 bg-transparent border-none text-sm text-white resize-none h-6 overflow-hidden" placeholder="输入 JavaScript 或 Playwright 命令..."></textarea>
        </div>
      </div>
    </div>
    `
  }

  /**
   * 格式化Playwright脚本
   * @param {string} script - 原始脚本内容
   * @returns {string} 格式化后的HTML内容
   */
  formatPlaywrightScript(script) {
    // 简单的语法高亮
    return script
      .replace(/import\s+{([^}]+)}\s+from\s+['"]([^'"]+)['"]/g, '<span class="text-blue-300">import {$1} from \'<span class="text-amber-300">$2</span>\';</span>')
      .replace(/test\(/g, '<span class="text-green-300">test<span class="text-blue-300">(</span></span>')
      .replace(/(await\s+page[.\w]+\()/g, '<span class="text-blue-300">$1</span>')
      .replace(/(['"])([^'"]+)(['"])/g, '<span class="text-amber-300">$1$2$3</span>')
      .replace(/\n/g, '<br>')
  }

}

// 创建单例实例
export const scriptManager = new ScriptManager()

// 导出便捷方法
export const {
  importScript,
  exportScript,
  getCurrentScript,
  setCurrentScript,
  getCurrentSteps,
  getScriptMetadata,
  setStepsAndUpdateUI,
  autoImportGeneratedScript
} = scriptManager
